package com.indicator.spring.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StopWatch;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author 超
 * Create by fengc on  2022/9/22 20:11
 */
@Slf4j
public class PerformanceInteceptor implements HandlerInterceptor {

    private ThreadLocal<StopWatch> threadLocal = new ThreadLocal<>();

    /**
     * 在业务处理器处理请求之前被调用。预处理，可以进行编码、安全控制、权限校验等处理；
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        StopWatch stopWatch= new StopWatch();
        threadLocal.set(stopWatch);
        stopWatch.start();
        return true;
    }

    /**
     * 在业务处理器处理请求执行完成后，生成视图之前执行。后处理（调用了Service并返回ModelAndView，但未进行页面渲染），有机会修改ModelAndView
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        threadLocal.get().stop();
        threadLocal.get().start();
    }

    /**
     * 在DispatcherServlet完全处理完请求后被调用，可用于清理资源等。返回处理（已经渲染了页面）；
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
        StopWatch stopWatch = threadLocal.get();
        stopWatch.stop();
        String method = handler.getClass().getSimpleName();
        log.info(".....handler.getClass().getSimpleName()={}",method);
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            String beanType = handlerMethod.getBeanType().getName();
            String methodName = handlerMethod.getMethod().getName();
            method = beanType + "." + methodName;
            log.info("......method={}",method);
        }
        log.info("{};{};{};{};{}ms;{}ms;{}ms", request.getRequestURI(), method,
                response.getStatus(), ex == null ? "-" : ex.getClass().getSimpleName(),
                stopWatch.getTotalTimeMillis(), stopWatch.getTotalTimeMillis() - stopWatch.getLastTaskTimeMillis(),
                stopWatch.getLastTaskTimeMillis());
        threadLocal.remove();
    }
}
